home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Arsenal Files 8
/
The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO
/
g_quake
/
bombs9.zip
/
WEAPONS.QC
< prev
Wrap
Text File
|
1996-10-15
|
44KB
|
1,920 lines
/*
Bouncing Fragmentation Grenade! 7/28/96 by Steve Bond
Email: wedge@nuc.net WWW: http://www.nuc.net/quake
>>>READ THE README!
Hey ID!
If you are reading this, PUH-LEEZE fly me and John to Texas!
We'll scrub the shitters at id for the chance to shake hands!
(I mean - we'll wash our hands first and everything)
*/
void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
void () player_run;
void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
void(vector org, vector vel, float damage) SpawnBlood;
void() SuperDamageSound;
float bombtimer;
void() W_FireBomb;
void() BombTouch;
void() BombExplode;
void() BombExplosion;
void() ShrapnelExplode;
void() BombTime;
void() W_FireGIBGUN;
void() T_GIBTouch;
void() GIBExplode;
void() W_FireFLASH;
void() T_FlashTouch;
// called by worldspawn
void() W_Precache =
{
precache_sound ("weapons/r_exp3.wav"); // new rocket explosion
precache_sound ("weapons/rocket1i.wav"); // spike gun
precache_sound ("weapons/sgun1.wav");
precache_sound ("weapons/guncock.wav"); // player shotgun
precache_sound ("weapons/ric1.wav"); // ricochet (used in c code)
precache_sound ("weapons/ric2.wav"); // ricochet (used in c code)
precache_sound ("weapons/ric3.wav"); // ricochet (used in c code)
precache_sound ("weapons/spike2.wav"); // super spikes
precache_sound ("weapons/tink1.wav"); // spikes tink (used in c code)
precache_sound ("weapons/grenade.wav"); // grenade launcher
precache_sound ("weapons/bounce.wav"); // grenade bounce
precache_sound ("weapons/shotgn2.wav"); // super shotgun
precache_sound ("items/damage2.wav");
precache_sound ("player/tornoff2.wav");
precache_sound ("player/lburn1.wav");
precache_sound ("doors/airdoor2.wav");
};
float() crandom =
{
return 2*(random() - 0.5);
};
/*
================
W_FireAxe
================
*/
void() W_FireAxe =
{
local vector source;
local vector org;
source = self.origin + '0 0 16';
traceline (source, source + v_forward*64, FALSE, self);
if (trace_fraction == 1.0)
return;
org = trace_endpos - v_forward*4;
if (trace_ent.takedamage)
{
trace_ent.axhitme = 1;
SpawnBlood (org, '0 0 0', 20);
T_Damage (trace_ent, self, self, 20);
}
else
{ // hit wall
sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_GUNSHOT);
WriteCoord (MSG_BROADCAST, org_x);
WriteCoord (MSG_BROADCAST, org_y);
WriteCoord (MSG_BROADCAST, org_z);
}
};
//============================================================================
vector() wall_velocity =
{
local vector vel;
vel = normalize (self.velocity);
vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
vel = vel + 2*trace_plane_normal;
vel = vel * 200;
return vel;
};
/*
================
SpawnMeatSpray
================
*/
void(vector org, vector vel) SpawnMeatSpray =
{
local entity missile, mpuff;
local vector org;
missile = spawn ();
missile.owner = self;
missile.movetype = MOVETYPE_BOUNCE;
missile.solid = SOLID_NOT;
makevectors (self.angles);
missile.velocity = vel;
missile.velocity_z = missile.velocity_z + 250 + 50*random();
missile.avelocity = '3000 1000 2000';
// set missile duration
missile.nextthink = time + 1;
missile.think = SUB_Remove;
setmodel (missile, "progs/zom_gib.mdl");
setsize (missile, '0 0 0', '0 0 0');
setorigin (missile, org);
};
/*
================
SpawnBlood
================
*/
void(vector org, vector vel, float damage) SpawnBlood =
{
particle (org, vel*0.1, 73, damage*2);
};
/*
================
spawn_touchblood
================
*/
void(float damage) spawn_touchblood =
{
local vector vel;
vel = wall_velocity () * 0.2;
SpawnBlood (self.origin + vel*0.01, vel, damage);
};
/*
================
SpawnChunk
================
*/
void(vector org, vector vel) SpawnChunk =
{
particle (org, vel*0.02, 0, 10);
};
/*
==============================================================================
MULTI-DAMAGE
Collects multiple small damages into a single damage
==============================================================================
*/
entity multi_ent;
float multi_damage;
void() ClearMultiDamage =
{
multi_ent = world;
multi_damage = 0;
};
void() ApplyMultiDamage =
{
if (!multi_ent)
return;
T_Damage (multi_ent, self, self, multi_damage);
};
void(entity hit, float damage) AddMultiDamage =
{
if (!hit)
return;
if (hit != multi_ent)
{
ApplyMultiDamage ();
multi_damage = damage;
multi_ent = hit;
}
else
multi_damage = multi_damage + damage;
};
/*
==============================================================================
BULLETS
==============================================================================
*/
/*
================
TraceAttack
================
*/
void(float damage, vector dir) TraceAttack =
{
local vector vel, org;
vel = normalize(dir + v_up*crandom() + v_right*crandom());
vel = vel + 2*trace_plane_normal;
vel = vel * 200;
org = trace_endpos - dir*4;
if (trace_ent.takedamage)
{
SpawnBlood (org, vel*0.2, damage);
AddMultiDamage (trace_ent, damage);
}
else
{
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_GUNSHOT);
WriteCoord (MSG_BROADCAST, org_x);
WriteCoord (MSG_BROADCAST, org_y);
WriteCoord (MSG_BROADCAST, org_z);
}
};
/*
================
FireBullets
Used by shotgun, super shotgun, and enemy soldier firing
Go to the trouble of combining multiple pellets into a single damage call.
================
*/
void(float shotcount, vector dir, vector spread) FireBullets =
{
local vector direction;
local vector src;
makevectors(self.v_angle);
src = self.origin + v_forward*10;
src_z = self.absmin_z + self.size_z * 0.7;
ClearMultiDamage ();
while (shotcount > 0)
{
direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
traceline (src, src + direction*2048, FALSE, self);
if (trace_fraction != 1.0)
TraceAttack (4, direction);
shotcount = shotcount - 1;
}
ApplyMultiDamage ();
};
/*
================
W_FireShotgun
================
*/
void() W_FireShotgun =
{
local vector dir;
sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
self.punchangle_x = -2;
self.currentammo = self.ammo_shells = self.ammo_shells - 1;
dir = aim (self, 100000);
FireBullets (6, dir, '0.04 0.04 0');
};
/*
================
W_FireSuperShotgun
================
*/
void() W_FireSuperShotgun =
{
local vector dir;
if (self.currentammo == 1)
{
W_FireShotgun ();
return;
}
sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
self.punchangle_x = -4;
self.currentammo = self.ammo_shells = self.ammo_shells - 2;
dir = aim (self, 100000);
FireBullets (14, dir, '0.14 0.08 0');
};
/*
==============================================================================
ROCKETS
==============================================================================
*/
void() s_explode1 = [0, s_explode2] {};
void() s_explode2 = [1, s_explode3] {};
void() s_explode3 = [2, s_explode4] {};
void() s_explode4 = [3, s_explode5] {};
void() s_explode5 = [4, s_explode6] {};
void() s_explode6 = [5, SUB_Remove] {};
void() BecomeExplosion =
{
self.movetype = MOVETYPE_NONE;
self.velocity = '0 0 0';
self.touch = SUB_Null;
setmodel (self, "progs/s_explod.spr");
self.solid = SOLID_NOT;
s_explode1 ();
};
void() T_MissileTouch =
{
local float damg;
if (other == self.owner)
return; // don't explode on owner
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
damg = 100 + random()*20;
if (other.health)
{
if (other.classname == "monster_shambler")
damg = damg * 0.5; // mostly immune
T_Damage (other, self, self.owner, damg );
}
// don't do radius damage to the other, because all the damage
// was done in the impact
T_RadiusDamage (self, self.owner, 120, other);
// sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
self.origin = self.origin - 8*normalize(self.velocity);
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
BecomeExplosion ();
};
/*
================
W_FireRocket
================
*/
void() W_FireRocket =
{
local entity missile, mpuff;
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
self.punchangle_x = -2;
missile = spawn ();
missile.owner = self;
missile.movetype = MOVETYPE_FLYMISSILE;
missile.solid = SOLID_BBOX;
missile.classname = "Rocket";
// set missile speed
makevectors (self.v_angle);
missile.velocity = aim(self, 1000);
missile.velocity = missile.velocity * 1000;
missile.angles = vectoangles(missile.velocity);
missile.touch = T_MissileTouch;
// set missile duration
missile.nextthink = time + 5;
missile.think = SUB_Remove;
setmodel (missile, "progs/missile.mdl");
setsize (missile, '0 0 0', '0 0 0');
setorigin (missile, self.origin + v_forward*8 + '0 0 16');
};
/*
===============================================================================
LIGHTNING
===============================================================================
*/
/*
=================
LightningDamage
=================
*/
void(vector p1, vector p2, entity from, float damage) LightningDamage =
{
local entity e1, e2;
local vector f;
f = p2 - p1;
normalize (f);
f_x = 0 - f_y;
f_y = f_x;
f_z = 0;
f = f*16;
e1 = e2 = world;
traceline (p1, p2, FALSE, self);
if (trace_ent.takedamage)
{
particle (trace_endpos, '0 0 100', 225, damage*4);
T_Damage (trace_ent, from, from, damage);
if (self.classname == "player")
{
if (other.classname == "player")
trace_ent.velocity_z = trace_ent.velocity_z + 400;
}
}
e1 = trace_ent;
traceline (p1 + f, p2 + f, FALSE, self);
if (trace_ent != e1 && trace_ent.takedamage)
{
particle (trace_endpos, '0 0 100', 225, damage*4);
T_Damage (trace_ent, from, from, damage);
}
e2 = trace_ent;
traceline (p1 - f, p2 - f, FALSE, self);
if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
{
particle (trace_endpos, '0 0 100', 225, damage*4);
T_Damage (trace_ent, from, from, damage);
}
};
void() W_FireLightning =
{
local vector org;
if (self.ammo_cells < 1)
{
self.weapon = W_BestWeapon ();
W_SetCurrentAmmo ();
return;
}
// explode if under water
if (self.waterlevel > 1)
{
T_RadiusDamage (self, self, 35*self.ammo_cells, world);
self.ammo_cells = 0;
W_SetCurrentAmmo ();
return;
}
if (self.t_width < time)
{
sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
self.t_width = time + 0.6;
}
self.punchangle_x = -2;
self.currentammo = self.ammo_cells = self.ammo_cells - 1;
org = self.origin + '0 0 16';
traceline (org, org + v_forward*600, TRUE, self);
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
WriteEntity (MSG_BROADCAST, self);
WriteCoord (MSG_BROADCAST, org_x);
WriteCoord (MSG_BROADCAST, org_y);
WriteCoord (MSG_BROADCAST, org_z);
WriteCoord (MSG_BROADCAST, trace_endpos_x);
WriteCoord (MSG_BROADCAST, trace_endpos_y);
WriteCoord (MSG_BROADCAST, trace_endpos_z);
LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
};
//=============================================================================
void() GrenadeExplode =
{
T_RadiusDamage (self, self.owner, 120, world);
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
BecomeExplosion ();
};
void() GrenadeTouch =
{
if (other == self.owner)
return; // don't explode on owner
if (other.takedamage == DAMAGE_AIM)
{
GrenadeExplode();
return;
}
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
if (self.velocity == '0 0 0')
self.avelocity = '0 0 0';
};
/*
================
W_FireGrenade
================
*/
void() W_FireGrenade =
{
local entity missile, mpuff;
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
self.punchangle_x = -2;
missile = spawn ();
missile.owner = self;
missile.movetype = MOVETYPE_BOUNCE;
missile.solid = SOLID_BBOX;
missile.classname = "grenade";
// set missile speed
makevectors (self.v_angle);
if (self.v_angle_x)
missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
else
{
missile.velocity = aim(self, 10000);
missile.velocity = missile.velocity * 600;
missile.velocity_z = 200;
}
missile.avelocity = '300 300 300';
missile.angles = vectoangles(missile.velocity);
missile.touch = GrenadeTouch;
// set missile duration
missile.nextthink = time + 2.5;
missile.think = GrenadeExplode;
setmodel (missile, "progs/grenade.mdl");
setsize (missile, '0 0 0', '0 0 0');
setorigin (missile, self.origin);
};
//=============================================================================
void() spike_touch;
void() superspike_touch;
/*
===============
launch_spike
Used for both the player and the ogre
===============
*/
void(vector org, vector dir) launch_spike =
{
newmis = spawn ();
newmis.owner = self;
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.solid = SOLID_BBOX;
newmis.angles = vectoangles(dir);
newmis.touch = spike_touch;
newmis.classname = "spike";
newmis.think = SUB_Remove;
// Bump the nail's lifespan up to 11 seconds(?),so it will stick for a bit
newmis.nextthink = time + 11;
setmodel (newmis, "progs/spike.mdl");
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
setorigin (newmis, org);
newmis.velocity = dir * 1000;
};
void() W_FireSuperSpikes =
{
local vector dir;
local entity old;
sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
self.attack_finished = time + 0.2;
self.currentammo = self.ammo_nails = self.ammo_nails - 2;
dir = aim (self, 1000);
launch_spike (self.origin + '0 0 16', dir);
newmis.touch = superspike_touch;
setmodel (newmis, "progs/s_spike.mdl");
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
self.punchangle_x = -2;
};
void(float ox) W_FireSpikes =
{
local vector dir;
local entity old;
makevectors (self.v_angle);
if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
{
W_FireSuperSpikes ();
return;
}
if (self.ammo_nails < 1)
{
self.weapon = W_BestWeapon ();
W_SetCurrentAmmo ();
return;
}
sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
self.attack_finished = time + 0.2;
self.currentammo = self.ammo_nails = self.ammo_nails - 1;
dir = aim (self, 1000);
launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
self.punchangle_x = -2;
};
.float hit_z;
void() spike_touch =
{
local float rand;
if (other == self.owner)
return;
if (other.solid == SOLID_TRIGGER)
return; // trigger field, do nothing
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
// hit something that bleeds
if (other.takedamage)
{
spawn_touchblood (9);
T_Damage (other, self, self.owner, 9);
remove(self);
}
else
{
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
if (self.classname == "wizspike")
WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
else if (self.classname == "knightspike")
WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
else
WriteByte (MSG_BROADCAST, TE_SPIKE);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
}
/*
DO NOT let the nail remove itself. This section of code is only executed
when the nail has hit a wall, floor, or plat. These are places we want the
nail to stick, so we comment out the REMOVE(SELF); function call
*/
self.velocity='0 0 0'; // make the nail stop!
remove(self);
};
void() superspike_touch =
{
local float rand;
if (other == self.owner)
return;
if (other.solid == SOLID_TRIGGER)
return; // trigger field, do nothing
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
// hit something that bleeds
if (other.takedamage)
{
spawn_touchblood (18);
T_Damage (other, self, self.owner, 18);
}
else
{
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
}
remove(self);
};
/*========================================================================
BOUNCING FRAGMENTATION GRENADE - Version .9
7/28/96 - Steve Bond email:wedge@nuc.net
http://www.nuc.net/quake
=======================================================================*/
//This code segment handles the impact of shrapnel
//this is merely id's superspike_touch code, reworked
void() shrapnel_touch =
{
local float rand;
// has the shrapnel hit a switch?
if (other.solid == SOLID_TRIGGER)
return; // trigger field, do nothing
// has the shrapnel hit the sky?
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
// has the shrapnel hit a living thing?
if (other.takedamage)
{
spawn_touchblood (18);
T_Damage (other, self, self.owner, 18);
}
else
{
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
}
};
/*
Code to spawn ONE randomly directed piece of shrapnel
this is id's launch_spike code, reworked
Pass a vector to this function to determine the shrap's origin
*/
void (vector org, float spin, entity shooter) launch_shrapnel=
{
local float xdir,ydir,zdir;
//Assign a random direction for the shrapnel to fly in
xdir = 110 * random() - 55;
ydir = 110 * random() - 55;
zdir = 50 * random() - 25;
newmis = spawn ();
newmis.owner = shooter;
newmis.movetype = MOVETYPE_BOUNCE;
self.touch = SUB_Null;
newmis.solid = SOLID_BBOX;
newmis.touch = shrapnel_touch;
newmis.classname = "spike";
newmis.think = ShrapnelExplode;
// this is how many seconds(?) the nails can exist.
newmis.nextthink = time + 0.75;
// speed at which to move the shrapnel
newmis.velocity_x = xdir * 5;
newmis.velocity_y = ydir * 5;
newmis.velocity_z = zdir * 10;
/*
as best I can figure, AVELOCITY means "attitude velocity"
or something thereabouts. Anyway, it makes shit spin on
the x,y,z axes by the given velocity for each axis. In this
case, it makes the shrapnel spin in flight. Good stuff.
this segment assigns one of five preset attitudes for
each piece of shrapnel, based on the number passed to the
function.
*/
if (spin == 0)
newmis.avelocity='250 300 400';
if (spin == 1)
newmis.avelocity='400 250 300';
if (spin == 2)
newmis.avelocity='300 400 250';
if (spin == 3)
newmis.avelocity='300 300 300';
if (spin == 4)
newmis.avelocity='400 250 400';
setmodel (newmis, "progs/grenade.mdl");
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
setorigin (newmis, org);
};
// This code segment detonates the 'second stage' of the grenade
// (After it has popped up)
void() BouncerExplode =
{
// Do the damage
T_RadiusDamage (self, self.owner, 120, world);
// Tell the network
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
// Let Quake handle the explosion and deallocation of the grenade
self.solid=SOLID_NOT;
BecomeExplosion ();
// Launch a hail (20 pieces) of shrapnel
launch_shrapnel (self.origin + '0 0 -1',0,self.owner);
launch_shrapnel (self.origin + '0 0 -1',1,self.owner);
launch_shrapnel (self.origin + '0 0 -1',2,self.owner);
launch_shrapnel (self.origin + '0 0 -1',3,self.owner);
launch_shrapnel (self.origin + '0 0 -1',4,self.owner);
launch_shrapnel (self.origin + '0 0 -1',0,self.owner);
launch_shrapnel (self.origin + '0 0 -1',1,self.owner);
launch_shrapnel (self.origin + '0 0 -1',2,self.owner);
launch_shrapnel (self.origin + '0 0 -1',3,self.owner);
launch_shrapnel (self.origin + '0 0 -1',4,self.owner);
};
/*
This code segment makes the 'first stage' of the bouncer pop upward
after it's time has expired.
*/
void() BouncerTouch;
void() BouncerPopUp=
{
local entity missile, mpuff;
// Make the grenade stop
self.movetype=MOVETYPE_NONE;
self.velocity='0 0 0';
// Draw a tiny explosion (no particles)
setmodel (self, "progs/s_explod.spr");
s_explode1 ();
// Make the :FOOMP: grenade launcher sound
sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
// Spawn and animate the 'second stage'
missile = spawn ();
missile.owner = self.owner;
missile.movetype = MOVETYPE_BOUNCE;
missile.solid = SOLID_BBOX;
missile.classname = "grenade";
// Set speed
missile.velocity = '0 0 650';
missile.angles = vectoangles(missile.velocity);
missile.touch = BouncerTouch;
// Set Duration
missile.nextthink = time + 1;
missile.think = BouncerExplode;
setmodel (missile, "progs/missile.mdl");
setsize (missile, '0 0 0', '0 0 0');
setorigin (missile, self.origin);
};
// This code segment handles collisions for the 'first stage'
// Of the grenade (after launch and before popup)
void() BouncerTouch =
{
//Did the grenade hit a 'living' thing?
if (other.takedamage)
{
// yes, so play the bounce sound
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
// now, exit the function without cause damage to the thing
return;
}
// This controls what happens when the grenade hits walls, etz
// It just plays the sound and bounces on
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
if (self.velocity == '0 0 0')
self.avelocity = '0 0 0';
};
/*
This code segment handles the launching of the Bouncing Fragmentation Grenade
this is a reworked copy of id's W_launchgrenade code
*/
void() W_LaunchBouncer =
{
// If player doesn't have 3 or more rockets, don't launch
if ((self.ammo_rockets < 5) || !(self.weapon & (IT_GRENADE_LAUNCHER | IT_FIREWALL | IT_BOMB)))
{
return;
}
local entity missile, mpuff;
// Take 3 rockets from the player
self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
//sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
/*
self.punchangle_x (x, y, or z) defines how hard the weapon
recoils (or 'punches' the player, making the screen shake)
*/
self.punchangle_x = -2;
// This spawns the grenade - it is all id's standard grenade code
missile = spawn ();
missile.owner = self;
missile.movetype = MOVETYPE_BOUNCE;
missile.solid = SOLID_BBOX;
missile.classname = "grenade";
// set missile speed
makevectors (self.v_angle);
if (self.v_angle_x)
missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
else
{
missile.velocity = aim(self, 10000);
missile.velocity = missile.velocity * 600;
missile.velocity_z = 200;
}
missile.avelocity = '300 300 300';
missile.angles = vectoangles(missile.velocity);
// if the grenade touches anything, BouncerTouch() is called
missile.touch = BouncerTouch;
// Grenade has a maximum lifespan of 1.5 (seconds?)
// set missile duration
missile.nextthink = time + 1;
// when the grenade's lifespan has expired, BouncerPopUp() is called
missile.think = BouncerPopUp;
setmodel (missile, "progs/grenade.mdl");
setsize (missile, '0 0 0', '0 0 0');
setorigin (missile, self.origin);
// sprint(self,"Gib 'em!\n");
};
/*
===============================================================================
End of Bouncing Fragmentation Grenade code.
===============================================================================
*/
/*
PLAYER WEAPON USE
===============================================================================
*/
void() W_SetCurrentAmmo =
{
player_run (); // get out of any weapon firing states
self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
if (self.weapon == IT_AXE)
{
self.currentammo = 0;
self.weaponmodel = "progs/v_axe.mdl";
self.weaponframe = 0;
}
else if (self.weapon == IT_SHOTGUN)
{
self.currentammo = self.ammo_shells;
self.weaponmodel = "progs/v_shot.mdl";
self.weaponframe = 0;
self.items = self.items | IT_SHELLS;
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
self.currentammo = self.ammo_shells;
self.weaponmodel = "progs/v_shot2.mdl";
self.weaponframe = 0;
self.items = self.items | IT_SHELLS;
}
else if (self.weapon == IT_NAILGUN)
{
self.currentammo = self.ammo_nails;
self.weaponmodel = "progs/v_nail.mdl";
self.weaponframe = 0;
self.items = self.items | IT_NAILS;
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
self.currentammo = self.ammo_nails;
self.weaponmodel = "progs/v_nail2.mdl";
self.weaponframe = 0;
self.items = self.items | IT_NAILS;
}
else if ((self.weapon == IT_GRENADE_LAUNCHER) || (self.weapon == IT_FIREWALL) || (self.weapon == IT_BOMB))
{
self.currentammo = self.ammo_rockets;
self.weaponmodel = "progs/v_rock.mdl";
self.weaponframe = 0;
self.items = self.items | IT_ROCKETS;
}
else if (self.weapon == IT_ROCKET_LAUNCHER || (self.weapon == IT_GIBGUN) || (self.weapon == IT_FLASH))
{
self.currentammo = self.ammo_rockets;
self.weaponmodel = "progs/v_rock2.mdl";
self.weaponframe = 0;
self.items = self.items | IT_ROCKETS;
}
else if (self.weapon == IT_LIGHTNING)
{
self.currentammo = self.ammo_cells;
self.weaponmodel = "progs/v_light.mdl";
self.weaponframe = 0;
self.items = self.items | IT_CELLS;
}
else
{
self.currentammo = 0;
self.weaponmodel = "";
self.weaponframe = 0;
}
};
float() W_BestWeapon =
{
local float it;
it = self.items;
if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
return IT_LIGHTNING;
else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
return IT_SUPER_NAILGUN;
else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
return IT_SUPER_SHOTGUN;
else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
return IT_NAILGUN;
else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
return IT_SHOTGUN;
/*
if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
return IT_ROCKET_LAUNCHER;
else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
return IT_GRENADE_LAUNCHER;
*/
return IT_AXE;
};
float() W_CheckNoAmmo =
{
if (self.currentammo > 0)
return TRUE;
if (self.weapon == IT_AXE)
return TRUE;
self.weapon = W_BestWeapon ();
W_SetCurrentAmmo ();
// drop the weapon down
return FALSE;
};
/*
============
W_Attack
An attack impulse can be triggered now
============
*/
void() player_axe1;
void() player_axeb1;
void() player_axec1;
void() player_axed1;
void() player_shot1;
void() player_nail1;
void() player_light1;
void() player_rocket1;
void() W_Attack =
{
local float r;
if (!W_CheckNoAmmo ())
return;
makevectors (self.v_angle); // calculate forward angle for velocity
self.show_hostile = time + 1; // wake monsters up
if (self.weapon == IT_AXE)
{
sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
r = random();
if (r < 0.25)
player_axe1 ();
else if (r<0.5)
player_axeb1 ();
else if (r<0.75)
player_axec1 ();
else
player_axed1 ();
self.attack_finished = time + 0.5;
}
else if (self.weapon == IT_SHOTGUN)
{
player_shot1 ();
W_FireShotgun ();
self.attack_finished = time + 0.5;
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
player_shot1 ();
W_FireSuperShotgun ();
self.attack_finished = time + 0.7;
}
else if (self.weapon == IT_NAILGUN)
{
player_nail1 ();
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
player_nail1 ();
}
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
player_rocket1();
W_FireGrenade();
self.attack_finished = time + 0.6;
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
player_rocket1();
W_FireRocket();
self.attack_finished = time + 0.8;
}
else if (self.weapon == IT_LIGHTNING)
{
player_light1();
self.attack_finished = time + 0.1;
sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
}
else if (self.weapon == IT_FIREWALL)
{
W_LaunchBouncer();
self.attack_finished = time + 0.4;
}
else if (self.weapon == IT_BOMB)
{
W_FireBomb();
self.attack_finished = time + 0.8;
}
else if (self.weapon == IT_GIBGUN)
{
W_FireGIBGUN();
self.attack_finished = time + 0.4;
}
else if (self.weapon == IT_FLASH)
{
W_FireFLASH();
self.attack_finished = time + 1;
}
};
/*
============
W_ChangeWeapon
============
*/
void() W_ChangeWeapon =
{
local float it, am, fl;
it = self.items;
am = 0;
if (self.impulse == 1)
{
fl = IT_AXE;
}
else if (self.impulse == 2)
{
fl = IT_SHOTGUN;
if (self.ammo_shells < 1)
am = 1;
}
else if (self.impulse == 3)
{
fl = IT_SUPER_SHOTGUN;
if (self.ammo_shells < 2)
am = 1;
}
else if (self.impulse == 4)
{
fl = IT_NAILGUN;
if (self.ammo_nails < 1)
am = 1;
}
else if (self.impulse == 5)
{
fl = IT_SUPER_NAILGUN;
if (self.ammo_nails < 2)
am = 1;
}
else if (self.impulse == 6)
{
if (self.weapon == IT_GRENADE_LAUNCHER)
{
self.weapon = IT_FIREWALL;
centerprint(self,"Firewall mode\n");
return;
}
if (self.weapon == IT_FIREWALL)
{
self.weapon = IT_BOMB;
centerprint(self,"Proximity mine mode\n");
return;
}
fl = IT_GRENADE_LAUNCHER;
if (self.ammo_rockets < 1)
am = 1;
if (!am) centerprint(self,"Grenade Launcher Mode\n");
}
else if (self.impulse == 7)
{
if (self.weapon == IT_ROCKET_LAUNCHER)
{
self.weapon = IT_GIBGUN;
centerprint(self,"Gibgun mode\n");
return;
}
if (self.weapon == IT_GIBGUN)
{
self.weapon = IT_FLASH;
centerprint(self,"Flashgun mode\n");
return;
}
fl = IT_ROCKET_LAUNCHER;
if (self.ammo_rockets < 1)
am = 1;
if (!am) centerprint(self,"Rocket Launcher Mode\n");
}
else if (self.impulse == 8)
{
fl = IT_LIGHTNING;
if (self.ammo_cells < 1)
am = 1;
}
self.impulse = 0;
if (!(self.items & fl))
{ // don't have the weapon or the ammo
sprint (self, "no weapon.\n");
return;
}
if (am)
{ // don't have the ammo
sprint (self, "not enough ammo.\n");
return;
}
//
// set weapon, set ammo
//
self.weapon = fl;
W_SetCurrentAmmo ();
};
/*
============
CheatCommand
============
*/
void() CheatCommand =
{
if (deathmatch || coop)
return;
self.ammo_rockets = 100;
self.ammo_nails = 200;
self.ammo_shells = 100;
self.items = self.items |
IT_AXE |
IT_SHOTGUN |
IT_SUPER_SHOTGUN |
IT_NAILGUN |
IT_SUPER_NAILGUN |
IT_GRENADE_LAUNCHER |
IT_ROCKET_LAUNCHER |
IT_KEY1 | IT_KEY2;
self.ammo_cells = 200;
self.items = self.items | IT_LIGHTNING;
self.weapon = IT_ROCKET_LAUNCHER;
self.impulse = 0;
W_SetCurrentAmmo ();
};
/*
============
CycleWeaponCommand
Go to the next weapon with ammo
============
*/
void() CycleWeaponCommand =
{
local float it, am;
it = self.items;
self.impulse = 0;
while (1)
{
am = 0;
if (self.weapon == IT_LIGHTNING)
{
self.weapon = IT_AXE;
}
else if (self.weapon == IT_AXE)
{
self.weapon = IT_SHOTGUN;
if (self.ammo_shells < 1)
am = 1;
}
else if (self.weapon == IT_SHOTGUN)
{
self.weapon = IT_SUPER_SHOTGUN;
if (self.ammo_shells < 2)
am = 1;
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
self.weapon = IT_NAILGUN;
if (self.ammo_nails < 1)
am = 1;
}
else if (self.weapon == IT_NAILGUN)
{
self.weapon = IT_SUPER_NAILGUN;
if (self.ammo_nails < 2)
am = 1;
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
self.weapon = IT_GRENADE_LAUNCHER;
if (self.ammo_rockets < 1)
am = 1;
}
else if ((self.weapon == IT_GRENADE_LAUNCHER) || (self.weapon == IT_FIREWALL) || (self.weapon == IT_BOMB))
{
self.weapon = IT_ROCKET_LAUNCHER;
if (self.ammo_rockets < 1)
am = 1;
}
else if ((self.weapon == IT_ROCKET_LAUNCHER) || (self.weapon == IT_GIBGUN) || (self.weapon == IT_FLASH))
{
self.weapon = IT_LIGHTNING;
if (self.ammo_cells < 1)
am = 1;
}
if ( (self.items & self.weapon) && am == 0)
{
W_SetCurrentAmmo ();
return;
}
}
};
/*
============
ServerflagsCommand
Just for development
============
*/
void() ServerflagsCommand =
{
serverflags = serverflags * 2 + 1;
};
void() QuadCheat =
{
if (deathmatch || coop)
return;
self.super_time = 1;
self.super_damage_finished = time + 30;
self.items = self.items | IT_QUAD;
dprint ("quad cheat\n");
};
/*
============
ImpulseCommands
============
*/
void() ImpulseCommands =
{
if (self.impulse >= 1 && self.impulse <= 8)
W_ChangeWeapon ();
if (self.impulse == 9)
CheatCommand ();
if (self.impulse == 10)
CycleWeaponCommand ();
if (self.impulse == 11)
ServerflagsCommand ();
// PATCH FOR BOUNCERS
if (self.impulse == 20)
{
W_LaunchBouncer ();
self.attack_finished = time + 0.4;
}
if (self.impulse == 21)
{
W_FireBomb ();
self.attack_finished = time + 0.8;
}
if (self.impulse == 22)
{
W_FireGIBGUN ();
self.attack_finished = time + 0.4;
}
if (self.impulse == 23)
{
W_FireFLASH ();
self.attack_finished = time + 1;
}
if (self.impulse == 255)
QuadCheat ();
self.impulse = 0;
};
/*
============
W_WeaponFrame
Called every frame so impulse events can be handled as well as possible
============
*/
void() W_WeaponFrame =
{
if (time < self.attack_finished)
return;
ImpulseCommands ();
// check for attack
if (self.button0)
{
SuperDamageSound ();
W_Attack ();
}
};
/*
========
SuperDamageSound
Plays sound if needed
========
*/
void() SuperDamageSound =
{
if (self.super_damage_finished > time)
{
if (self.super_sound < time)
{
self.super_sound = time + 1;
sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
}
}
return;
};
/***********************************************************************************
================
W_FireBomb
================
************************************************************************************/
void() W_FireBomb =
{
local entity missile, mpuff;
if ((self.ammo_rockets < 5) || !(self.weapon & (IT_GRENADE_LAUNCHER | IT_FIREWALL | IT_BOMB )))
{
return;
}
if (bombtimer >0 )
{
return;
}
else bombtimer=1.5;
self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
self.punchangle_x = -10;
missile = spawn ();
missile.owner = self;
missile.movetype = MOVETYPE_FLY;
missile.solid = SOLID_TRIGGER;
missile.classname = "Bomb";
// set missile speed
makevectors (self.v_angle);
missile.velocity= '0 0 0';
missile.avelocity= '0 0 0';
missile.touch = BombTouch;
// set missile duration
missile.nextthink = time + 0.25;
missile.think = BombTime;
setmodel (missile, "progs/grenade.mdl");
setsize (missile, '-48 -48 -4', '48 48 4');
setorigin (missile, self.origin - '0 0 20');
// sprint(self,"Better stay the hell clear now\n");
};
void() BombTime =
{
bombtimer = bombtimer - 0.25;
if (bombtimer)
{
if (bombtimer == 0.5) self.velocity='0 0 24';
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
self.nextthink = time + 0.25;
self.think = BombTime;
}
else
{
self.nextthink = time + 180;
self.think = BecomeExplosion;
self.classname = "ArmedBomb";
self.velocity='0 0 0';
self.avelocity='0 800 800';
self.health = 20;
self.th_die = BombExplode;
self.takedamage = DAMAGE_AIM;
}
};
void() BombTouch =
{
if (other.takedamage && (self.classname == "ArmedBomb") && (other.classname != "ArmedBomb"))
{
BombExplode();
return;
}
};
void() BombExplode =
{
T_RadiusDamage (self, self.owner, 120, world);
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
BombExplosion ();
};
void() BombExplosion =
{
sound (self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM);
self.movetype = MOVETYPE_NONE;
self.velocity = '0 0 0';
self.touch = SUB_Null;
setmodel (self, "progs/s_explod.spr");
self.solid = SOLID_NOT;
s_explode1 ();
};
void() ShrapnelExplode =
{
T_RadiusDamage (self, self.owner, 120, world);
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
BecomeExplosion ();
};
void() GIBExplode =
{
local entity loser;
self.wait = self.wait - 1;
loser = self.trigger_field;
if ((self.wait == 30) || (self.wait == 20) || (self.wait == 10)) sound (self, CHAN_WEAPON, "player/tornoff2.wav", 1, ATTN_NORM);
if (((self.wait == 35) || (self.wait == 25) || (self.wait == 15)) && (loser.classname == "player")) sound (self, CHAN_WEAPON, "player/lburn1.wav", 1, ATTN_NORM);
if ((!self.wait) || (loser.health<=10))
{
T_RadiusDamage (self, self.owner, 120, world);
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
BecomeExplosion ();
return;
}
T_Damage (loser, self, self.owner, 2.5 );
spawn_touchblood (30);
self.origin = loser.origin + '0 0 12';
self.nextthink = time + 0.05;
self.think = GIBExplode;
};
void() T_GIBTouch =
{
local float damg;
if (other == self.owner)
return; // don't explode on owner
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
if (other.takedamage)
{
sound (self, CHAN_WEAPON, "player/tornoff2.wav", 1, ATTN_NORM);
self.trigger_field = other;
self.origin = other.origin + '0 0 12';
self.wait = 40;
self.nextthink = time + 0.05;
self.think = GIBExplode;
self.movetype = MOVETYPE_NOCLIP;
self.velocity = '0 0 0' ;
self.avelocity = '0 0 1000';
return;
}
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
// remove(self);
self.nextthink = time + 0.3;
self.think = SUB_Remove;
self.movetype = MOVETYPE_NOCLIP;
self.velocity = ' 0 0 0';
self.avelocity = '0 0 1000';
};
/*
================
W_FireGIBGUN
================
*/
void() W_FireGIBGUN =
{
if ((self.ammo_rockets < 1) || !(self.weapon & (IT_ROCKET_LAUNCHER | IT_GIBGUN | IT_FLASH)))
{
return;
}
local entity missile, mpuff;
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
self.punchangle_x = -2;
missile = spawn ();
missile.owner = self;
missile.movetype = MOVETYPE_FLYMISSILE;
missile.solid = SOLID_BBOX;
missile.classname = "GibGun";
// set missile speed
makevectors (self.v_angle);
missile.velocity = aim(self, 1000);
missile.velocity = missile.velocity * 1000;
missile.angles = vectoangles(missile.velocity);
missile.touch = T_GIBTouch;
// set missile duration
missile.nextthink = time + 5;
missile.think = SUB_Remove;
setmodel (missile, "progs/missile.mdl");
setsize (missile, '0 0 0', '0 0 0');
setorigin (missile, self.origin + v_forward*8 + '0 0 16');
};
/*
================
W_FireFlash
================
*/
void() W_FireFLASH =
{
if ((self.ammo_rockets < 5) || !(self.weapon & (IT_ROCKET_LAUNCHER | IT_GIBGUN | IT_FLASH)))
{
return;
}
local entity missile, mpuff;
self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
self.punchangle_x = -2;
missile = spawn ();
missile.owner = self;
missile.movetype = MOVETYPE_FLYMISSILE;
missile.solid = SOLID_BBOX;
missile.classname = "Flash";
// set missile speed
makevectors (self.v_angle);
missile.velocity = aim(self, 100000);
missile.velocity = missile.velocity * 800;
missile.angles = vectoangles(missile.velocity);
missile.touch = T_FlashTouch;
// set missile duration
missile.nextthink = time + 5;
missile.think = SUB_Remove;
setmodel (missile, "progs/missile.mdl");
setsize (missile, '0 0 0', '0 0 0');
setorigin (missile, self.origin + v_forward*8 + '0 0 16');
};
void() T_FlashTouch =
{
local float damg;
if (other == self.owner)
return; // don't explode on owner
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
self.effects = self.effects | EF_BRIGHTLIGHT;
damg = 20;
if (other.health)
{
if (other.classname == "monster_shambler")
damg = damg * 0.5; // mostly immune
T_Damage (other, self, self.owner, damg );
}
// don't do radius damage to the other, because all the damage
// was done in the impact
T_RadiusDamage (self, self.owner, 20, other);
T_FlashDamage (self, self.owner,1000, self);
sound (self, CHAN_WEAPON, "doors/airdoor2.wav", 1, ATTN_NORM);
self.origin = self.origin - 8*normalize(self.velocity);
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_EXPLOSION);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
BecomeExplosion ();
};